package com.changzhi.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.changzhi.common.constans.RedisConstans;
import com.changzhi.common.enums.PrizeTypeEnum;
import com.changzhi.common.exception.ServiceException;
import com.changzhi.common.util.DateUtil;
import com.changzhi.ldyl.model.*;
import com.changzhi.ldyl.model.dto.NewYearDto;
import com.changzhi.ldyl.model.vo.NewLotteryVo;
import com.changzhi.ldyl.model.vo.NewPrizeVo;
import com.changzhi.mapper.*;
import com.changzhi.service.ActivityCardService;
import com.changzhi.service.ActivityService;
import com.changzhi.service.GiftService;
import com.changzhi.service.NewYearService;
import com.changzhi.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;

/**
 * @Description:
 * @author: 小落
 * @date: 2020年11月16日
 */
@Slf4j
@Service
public class NewYearServiceImpl implements NewYearService {

	@Autowired
	private RedisUtil redisUtil;
	@Autowired
	private GiftService giftService;
	@Autowired
	private ActivityService activityService;
	@Autowired
	private ActivityRecordMapper activityRecordMapper;
	@Resource
	private UserWalletMapper userWalletMapper;
	@Resource
	private UserGiftMapper userGiftMapper;
	@Resource
	private ActivityCardMapper activityCardMapper;
	@Resource
	private GiftConfigMapper giftConfigMapper;
	@Resource
	private UserAccountBookMapper userAccountBookMapper;
	@Resource
	private SysDictMapper sysDictMapper;
	@Resource
	private DressUpConfigMapper dressUpConfigMapper;
	@Resource
	private ActivityWalletMapper activityWalletMapper;
	@Autowired
	private ActivityCardService activityCardService;
	//活动时间
	public static Map<String, LocalDateTime> TIME_MAP = new HashMap<>();
	//挂件列表
	public static List<NewPrizeVo> PENDANT_LIST = new ArrayList<>();
	//兑换奖品列表
	public static List<NewPrizeVo> EXCHANGE_PRIZE_LIST = new ArrayList<>();
	//翻牌奖品
	public static Map<Integer, NewLotteryVo> CARD_PRIZE_MAP = new HashMap<>();
	//免费翻牌奖品列表
	public static List<NewLotteryVo> FREE_CARD_PRIZE_LIST = new ArrayList<>();
	//截至兑奖时间
	public static final LocalDate EXCHANGE_END_TIME = LocalDate.of(2021,1,8);
	//活动id
	public static final Integer ACTIVITY_ID = 5;
	// 用户抽奖最大回合数-1
	private static final Integer USER_TOTAL_ROUND = 100;
	//每关卡最大翻牌数
	private static final Integer LEVEL_CARD_NUM = 20;
	//元旦奖品code
	private static final String PRIZE_CODE = "ACTIVITY_NEW_PRIZE";
	@Resource
	private Executor executor;
	@Resource
	private OrderDayMapper orderDayMapper;

	/*//初始化
	@PostConstruct
	public void init(){
		redisUtil.del(RedisConstans.ACTIVITY + ACTIVITY_ID);
		Activity activity = activityService.getActivity(ACTIVITY_ID);
		//活动时间
		TIME_MAP.put("startTime", activity.getStartTime());
		TIME_MAP.put("endTime", activity.getEndTime());
		//翻牌奖品列表
		List<NewLotteryVo> prizeList = sysDictMapper.selectPrizeList(PRIZE_CODE, null, null);
		for (NewLotteryVo newLotteryVo : prizeList) {
			switch (PrizeTypeEnum.getEnum(newLotteryVo.getType())){
				case FRAME:
				case CAR:
				case GIFT:
					Map<String, String> giftInfo = getGiftInfo(newLotteryVo.getGiftId());
					newLotteryVo.setName(giftInfo.get("name")).setIcon(giftInfo.get("icon"));
					break;
				case BUBBLE:
					Map<String, String> dressUpInfo = getDressUpInfo(newLotteryVo.getGiftId());
					newLotteryVo.setName(dressUpInfo.get("name")).setIcon(dressUpInfo.get("icon"));
					break;
				case LAMP:
					FREE_CARD_PRIZE_LIST.add(newLotteryVo);
			}
			CARD_PRIZE_MAP.put(newLotteryVo.getGiftId(), newLotteryVo);
		}
		//兑换奖品列表
		EXCHANGE_PRIZE_LIST = JSON.parseArray(activity.getProperty1(), NewPrizeVo.class);
		for (NewPrizeVo newPrizeVo : EXCHANGE_PRIZE_LIST) {
			Map<String, String> giftInfo = getGiftInfo(newPrizeVo.getGiftId());
			newPrizeVo.setName(giftInfo.get("name")).setIcon(giftInfo.get("icon"));
		}
		//挂件列表
		JSONArray jsonArray3 = JSON.parseArray(activity.getProperty2());
		for (int i = 0; i < jsonArray3.size(); i++) {
			NewPrizeVo pendant = new NewPrizeVo();
			Map<String, String> dressUpInfo = getDressUpInfo(jsonArray3.getInteger(i));
			pendant.setGiftId(jsonArray3.getInteger(i)).setType(6).setName(dressUpInfo.get("name")).setIcon(dressUpInfo.get("icon"));
			PENDANT_LIST.add(pendant);
		}
	}*/


	@Override
	public void doMqDataByUserGift(UserGift userGift) {
		//是否收礼或送礼达到10元
		String userId = userGift.getUserId();
		String targetId = userGift.getTargetId();
		//送礼人
		Boolean cache1 = redisUtil.get(RedisConstans.NEW_IS_MEDAL + userId);
		if(cache1 != null && cache1){
			return;
		}
		redisUtil.set(RedisConstans.NEW_IS_MEDAL + userId, checkGiveValue(userId), RedisConstans.ONE_MONTH);
		log.warn("methodName:元旦doMqDataByOrderSuccess，userId={}", userId);

		//收礼人
		Boolean cache2 = redisUtil.get(RedisConstans.NEW_IS_MEDAL + targetId);
		if(cache2 != null && cache2){
			return;
		}
		redisUtil.set(RedisConstans.NEW_IS_MEDAL + targetId, checkReceiveValue(targetId), RedisConstans.ONE_MONTH);
		log.warn("methodName:元旦doMqDataByOrderSuccess，targetId={}", targetId);

	}

	@Override
	public void doMqDataByOrderSuccess(String userId) {
		//是否充值达到10元
		executor.execute(()->{

		});

	}

	//判断送礼总值是否达到10元
	private boolean checkGiveValue(String userId){
		QueryWrapper<UserGift> wrapper1 = new QueryWrapper<>();
		wrapper1.lambda().eq(UserGift::getUserId, userId);
		wrapper1.select("ifnull(sum(total_gift_value),0) as total ");
		List<Map<String, Object>> list1 = userGiftMapper.selectMaps(wrapper1);
		Long value = Long.valueOf(String.valueOf(list1.get(0).get("total")));
		if(value >= 100){
			return true;
		}
		return false;
	}

	//判断收礼礼总值是否达到10元
	private boolean checkReceiveValue(String userId){
		//查收礼总值
		QueryWrapper<UserGift> wrapper2 = new QueryWrapper<>();
		wrapper2.lambda().eq(UserGift::getTargetId, userId);
		wrapper2.select("ifnull(sum(total_gift_value),0) as total ");
		List<Map<String, Object>> list2 = userGiftMapper.selectMaps(wrapper2);
		Long value = Long.valueOf(String.valueOf(list2.get(0).get("total")));
		if(value >= 100){
			return true;
		}
		return false;
	}


	@Override
	public Map<String, Object> cardList(NewYearDto newYearDto) {
		String userId = newYearDto.getUserId();
		Integer level = newYearDto.getLevel();
		//是否已领取火苗
		Integer receiveFlame = redisUtil.get(RedisConstans.NEW_IS_FLAME + LocalDate.now().toString() + ":" + userId);
		//查缓存
		/*Map<String, Object> result = redisUtil.get(RedisConstans.NEW_CARD + userId);
		if(result != null){
			result.put("receiveFlame", receiveFlame == null ? true : false);
			return result;
		}*/
		Map<String, Object> result = getCardList(userId, level);
		result.put("receiveFlame", receiveFlame == null ? true : false);
		//redisUtil.set(RedisConstans.NEW_CARD + userId, result, RedisConstans.ONE_HOUR);
		return result;
	}

	private Map<String, Object> getCardList(String userId, Integer level){
		Map<String, Object> result = new HashMap<>();
		List<NewPrizeVo> resultList = new ArrayList<>();
		//最大关卡
		boolean maxLevel = false;
		//查数据库,level为空表示当前关卡
		if(level == null){
			List<ActivityCard> list = activityCardMapper.selectListByMaxLevel(ACTIVITY_ID, userId);
			//空情况下
			if(CollectionUtils.isEmpty(list)){
				for (int i = 1; i <= LEVEL_CARD_NUM; i++) {
					NewPrizeVo prizeVo = new NewPrizeVo();
					prizeVo.setLocation(i);
					resultList.add(prizeVo);
				}
				result.put("level", 1);
			} else if(list.size() >= LEVEL_CARD_NUM){
				//当前关卡翻开20个以上情况下,进去下一关卡
				for (int i = 1; i <= LEVEL_CARD_NUM; i++) {
					NewPrizeVo prizeVo = new NewPrizeVo();
					prizeVo.setLocation(i);
					resultList.add(prizeVo);
				}
				result.put("level", list.get(0).getLevel() + 1);
			} else {
				//当前关卡数据
				Map<Integer, List<ActivityCard>> groupMap = list.stream().collect(Collectors.groupingBy(ActivityCard::getLocation));
				for (int i = 1; i <= LEVEL_CARD_NUM; i++) {
					NewPrizeVo prizeVo = new NewPrizeVo();
					List<ActivityCard> cards = groupMap.get(i);
					if(CollectionUtils.isEmpty(cards)){
						prizeVo.setLocation(i);
					} else {
						BeanUtils.copyProperties(cards.get(0), prizeVo);
						prizeVo.setLevel(null);
					}
					resultList.add(prizeVo);
				}
				result.put("level", list.get(0).getLevel());
			}
			maxLevel =  true;
		} else {
			//可查看的最大关卡
			ActivityCard dataRecord = activityCardMapper.selectInfoByMaxLevel(ACTIVITY_ID, userId);
			if(dataRecord.getNum() >= LEVEL_CARD_NUM){
				dataRecord.setLevel(dataRecord.getLevel() + 1);
			}
			if(level > dataRecord.getLevel()){
				throw new ServiceException("下一关卡未解锁");
			} else if(level.equals(dataRecord.getLevel())){
				maxLevel = true;
			}
			LambdaQueryWrapper<ActivityCard> wrapper = new LambdaQueryWrapper<>();
			wrapper.eq(ActivityCard::getActivityId, ACTIVITY_ID).eq(ActivityCard::getUserId, userId).eq(ActivityCard::getLevel, level);
			wrapper.orderByAsc(ActivityCard::getLevel).orderByAsc(ActivityCard::getLocation);
			List<ActivityCard> list = activityCardMapper.selectList(wrapper);
			Map<Integer, List<ActivityCard>> groupMap = list.stream().collect(Collectors.groupingBy(ActivityCard::getLocation));
			for (int i = 1; i <= LEVEL_CARD_NUM; i++) {
				NewPrizeVo prizeVo = new NewPrizeVo();
				List<ActivityCard> cards = groupMap.get(i);
				if(CollectionUtils.isEmpty(cards)){
					prizeVo.setLocation(i);
				} else {
					BeanUtils.copyProperties(cards.get(0), prizeVo);
					prizeVo.setLevel(null);
				}
				resultList.add(prizeVo);
			}
			result.put("level", level);
		}
		result.put("maxLevel", maxLevel);
		result.put("list", resultList);
		return result;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public NewPrizeVo openCard(NewYearDto newYearDto) {
		String userId = newYearDto.getUserId();
		Integer level = newYearDto.getLevel();
		Integer location = newYearDto.getLocation();
		boolean nextLevel = false;
		if(level == null){
			throw new ServiceException("关卡不能为空");
		}
		if(location == null){
			throw new ServiceException("位置不能为空");
		}
		//判断是否重复翻牌
		NewLotteryVo cache = (NewLotteryVo) redisUtil.hget(RedisConstans.NEW_LOTTERY_RECORD + userId, level + "_" + location);
		if(cache != null){
			throw new ServiceException("请勿重复翻牌");
		}
		//判断是否越关卡翻牌
		ActivityCard dataRecord = activityCardMapper.selectInfoByMaxLevel(ACTIVITY_ID, userId);
		if(level != 1){
			if(dataRecord.getNum() < LEVEL_CARD_NUM && !level.equals(dataRecord.getLevel())){
				throw new ServiceException("翻牌关卡有误");
			} else if(dataRecord.getNum() >= LEVEL_CARD_NUM && !level.equals(dataRecord.getLevel() + 1)){
				throw new ServiceException("翻牌关卡有误");
			}
		}
		//是否进入下一关卡
		if(dataRecord.getNum() == (LEVEL_CARD_NUM - 1)){
			nextLevel = true;
		}
		//是否有收送礼达到10元以上
		boolean flag = checkMedal(userId);
		//判断火苗数是否足够
		ActivityWallet activityWallet = getActivityWallet(userId);
		if (activityWallet == null || activityWallet.getAmount1() < 10) {
			throw new ServiceException("小火苗数不足");
		}
		//扣除火苗
		int row = activityWalletMapper.reduceAmount1(activityWallet.getId(), 10);
		if(row < 1){
			throw new ServiceException("翻牌失败，请稍后重试");
		}
		//今天是否抽过奖
		Integer dayLottery = redisUtil.get(RedisConstans.NEW_IS_CARD + userId + "_" + LocalDate.now().toString());
		Integer hasReceiveFlame = redisUtil.get(RedisConstans.NEW_IS_FLAME + LocalDate.now().toString() + ":" + userId);
		//抽取礼物
		NewLotteryVo newLotteryVo;
		if(flag){
			if(hasReceiveFlame != null && dayLottery == null){
				//抽小礼物
				newLotteryVo = lottery(userId, 1);
			} else {
				newLotteryVo = lottery(userId, null);
			}
		} else{
			//相当于免费的抽奖
			newLotteryVo = randomPrize(FREE_CARD_PRIZE_LIST);
		}
		//保存卡牌
		ActivityCard card = new ActivityCard();
		card.setActivityId(ACTIVITY_ID);
		card.setUserId(userId);
		card.setLevel(level);
		card.setLocation(location);
		card.setGiftId(newLotteryVo.getGiftId());
		card.setName(newLotteryVo.getName());
		card.setIcon(newLotteryVo.getIcon());
		card.setNum(newLotteryVo.getNum());
		activityCardMapper.insert(card);
		//保存奖品
		switch (PrizeTypeEnum.getEnum(newLotteryVo.getType())){
			case FRAME:
			case CAR:
			case GIFT:
				//异步保存礼物
				executor.execute(()->{giftService.savePrize(ACTIVITY_ID, userId, newLotteryVo.getGiftId(), null,1);});
				break;
			case BUBBLE:
				redisUtil.set(RedisConstans.NEW_BUBBLE + userId, 1, RedisConstans.ONE_MONTH);
				giftService.saveUserDress(ACTIVITY_ID, userId, newLotteryVo.getGiftId(), 1);
				break;
			case FLAME:
				//增加火苗数
				activityWalletMapper.addAmount1(activityWallet.getId(), newLotteryVo.getNum());
				//插入领取记录表
				insertRecord(userId, newLotteryVo.getGiftId(), newLotteryVo.getName(), newLotteryVo.getValue());
				break;
			case LAMP:
				//增加灯笼数
				activityWalletMapper.addAmount2(activityWallet.getId(), newLotteryVo.getNum());
				//插入领取记录表
				insertRecord(userId, newLotteryVo.getGiftId(), newLotteryVo.getName(), newLotteryVo.getValue());
				break;
		}
		//是否达到获得挂件需求
		Integer num = redisUtil.get(RedisConstans.NEW_CARD_NUM + userId);
		Integer flame = num == null ? 0 : num * 10;
		NewPrizeVo pendant = null;
		if (flame >= 10000) {
			pendant = PENDANT_LIST.get(4);
		} else if (flame >= 5000) {
			pendant = PENDANT_LIST.get(3);
		} else if (flame >= 1000) {
			pendant = PENDANT_LIST.get(2);
		} else if (flame >= 500) {
			pendant = PENDANT_LIST.get(1);
		} else if (flame >= 100) {
			pendant = PENDANT_LIST.get(0);
		}
		//给用户添加挂件
		if(pendant != null && redisUtil.hget(RedisConstans.NEW_PENDANT + userId, pendant.getGiftId() + "") == null){
			redisUtil.hset(RedisConstans.NEW_PENDANT + userId, pendant.getGiftId() + "", pendant, RedisConstans.ONE_MONTH);
			NewPrizeVo finalPendant = pendant;
			executor.execute(()->{
				giftService.saveUserDress(ACTIVITY_ID, userId, finalPendant.getGiftId(), 1);
			});
		} else {
			pendant = null;
		}
		//返回
		NewPrizeVo result = new NewPrizeVo();
		result.setLevel(level)
				.setLocation(location)
				.setIcon(newLotteryVo.getIcon())
				.setType(newLotteryVo.getType())
				.setName(newLotteryVo.getName()).setGiftId(newLotteryVo.getGiftId())
				.setPendant(pendant)
				.setNextLevel(nextLevel);
		//保存翻牌记录到缓存
		redisUtil.hset(RedisConstans.NEW_LOTTERY_RECORD + userId, level + "_" + location, newLotteryVo, RedisConstans.ONE_MONTH);
		//计算翻牌总数
		redisUtil.incr(RedisConstans.NEW_CARD_NUM + userId);
		redisUtil.expire(RedisConstans.NEW_CARD_NUM + userId, RedisConstans.ONE_MONTH);
		//删除列表缓存
		//redisUtil.del(RedisConstans.NEW_CARD + userId);
		log.info("methodName:openCard,翻牌成功,result={}", JSON.toJSONString(result));
		//表示今天已经抽过奖
		if(dayLottery == null && hasReceiveFlame != null){
			redisUtil.set(RedisConstans.NEW_IS_CARD + userId + "_" + LocalDate.now().toString(), 1, RedisConstans.ONE_MONTH);
		}
		return result;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Map<String, Object> openCardByLevel(NewYearDto newYearDto) {
		String userId = newYearDto.getUserId();
		Integer level = newYearDto.getLevel();
		if(level == null){
			throw new ServiceException("关卡不能为空");
		}
		//判断是否越关卡翻牌
		List<ActivityCard> cardList = activityCardMapper.selectListByMaxLevel(ACTIVITY_ID, userId);
		ActivityCard dataRecord = activityCardMapper.selectInfoByMaxLevel(ACTIVITY_ID, userId);
		if(cardList.size() >= 20 && !level.equals(dataRecord.getLevel() + 1)){
			throw new ServiceException("当前关卡已翻完牌");
		}
		if(level != 1){
			if(cardList.size() < LEVEL_CARD_NUM && !level.equals(dataRecord.getLevel())){
				throw new ServiceException("翻牌关卡有误");
			} else if(dataRecord.getNum() >= LEVEL_CARD_NUM && !level.equals(dataRecord.getLevel() + 1)){
				throw new ServiceException("翻牌关卡有误");
			}
		}
		if(cardList.size() >= 20 && level.equals(dataRecord.getLevel() + 1)){
			cardList = new ArrayList<>();
		}
		//判断火苗数是否足够
		Integer num = LEVEL_CARD_NUM - cardList.size(); //翻牌个数
		Integer needFlame = (LEVEL_CARD_NUM - cardList.size()) * 10; //需要火苗数
		ActivityWallet activityWallet = getActivityWallet(userId);
		if (activityWallet == null || activityWallet.getAmount1() < needFlame) {
			throw new ServiceException("小火苗数不足");
		}
		//扣除火苗
		int row = activityWalletMapper.reduceAmount1(activityWallet.getId(), needFlame);
		if(row < 1){
			throw new ServiceException("翻牌失败，请稍后重试");
		}
		//抽取礼物
		//保存卡牌 和抽奖
		List<NewPrizeVo> resultList = new ArrayList<>();
		List<NewLotteryVo> newLotteryVoList = new ArrayList<>();
		List<ActivityCard> recordList = new ArrayList<>();
		Map<String, NewLotteryVo> redisRecord = new HashMap<>();
		Map<Integer, List<ActivityCard>> groupMap = cardList.stream().collect(Collectors.groupingBy(ActivityCard::getLocation));
		//是否有翻到气泡框
		Integer cache = redisUtil.get(RedisConstans.NEW_BUBBLE + userId);
		//查翻牌所有奖品
		List<NewLotteryVo> prizeList = sysDictMapper.selectPrizeList(PRIZE_CODE, cache, null);
		for (int i = 1; i <= LEVEL_CARD_NUM; i++) {
			NewPrizeVo prizeVo = new NewPrizeVo();
			List<ActivityCard> cards = groupMap.get(i);
			if(CollectionUtils.isEmpty(cards)){
				//翻牌
				NewLotteryVo newLotteryVo = lotteryBatch(userId, prizeList);
				if(newLotteryVo.getType() == 2){
					//移除气泡框奖品
					Iterator<NewLotteryVo> iterator = prizeList.iterator();
					while (iterator.hasNext()){
						NewLotteryVo next = iterator.next();
						if(next.getType().equals(2)){
							iterator.remove();
							break;
						}
					}
				}
				newLotteryVoList.add(newLotteryVo);
				BeanUtils.copyProperties(newLotteryVo, prizeVo);
				//生成卡牌记录
				ActivityCard card = new ActivityCard();
				card.setActivityId(ACTIVITY_ID);
				card.setUserId(userId);
				card.setLevel(level);
				card.setLocation(i);
				card.setGiftId(newLotteryVo.getGiftId());
				card.setName(newLotteryVo.getName());
				card.setIcon(newLotteryVo.getIcon());
				card.setNum(newLotteryVo.getNum());
				recordList.add(card);
				//保存翻牌记录到缓存
				redisRecord.put(level + "_" + i, newLotteryVo);
			} else {
				BeanUtils.copyProperties(cards.get(0), prizeVo);
				prizeVo.setLevel(null);
			}
			resultList.add(prizeVo);
		}
		for (NewLotteryVo newLotteryVo : newLotteryVoList) {
			//保存奖品
			switch (PrizeTypeEnum.getEnum(newLotteryVo.getType())){
			case FRAME:
			case CAR:
			case GIFT:
				//异步保存礼物
				executor.execute(()->{giftService.savePrize(ACTIVITY_ID, userId, newLotteryVo.getGiftId(), null,1);});
				break;
			case BUBBLE:
				redisUtil.set(RedisConstans.NEW_BUBBLE + userId, 1, RedisConstans.ONE_MONTH);
				giftService.saveUserDress(ACTIVITY_ID, userId, newLotteryVo.getGiftId(), 1);
				break;
			case FLAME:
				//增加火苗数
				activityWalletMapper.addAmount1(activityWallet.getId(), newLotteryVo.getNum());
				//插入领取记录表
				insertRecord(userId, newLotteryVo.getGiftId(), newLotteryVo.getName(), newLotteryVo.getValue());
				break;
			case LAMP:
				//增加灯笼数
				activityWalletMapper.addAmount2(activityWallet.getId(), newLotteryVo.getNum());
				//插入领取记录表
				insertRecord(userId, newLotteryVo.getGiftId(), newLotteryVo.getName(), newLotteryVo.getValue());
				break;
			}
		}
		//是否达到获得挂件需求
		Integer count = redisUtil.get(RedisConstans.NEW_CARD_NUM + userId);
		if(count == null){
			count = 0;
		}
		count += num;
		Integer flame = count * 10;
		NewPrizeVo pendant = null;
		if (flame >= 10000) {
			pendant = PENDANT_LIST.get(4);
		} else if (flame >= 5000) {
			pendant = PENDANT_LIST.get(3);
		} else if (flame >= 1000) {
			pendant = PENDANT_LIST.get(2);
		} else if (flame >= 500) {
			pendant = PENDANT_LIST.get(1);
		} else if (flame >= 100) {
			pendant = PENDANT_LIST.get(0);
		}
		//给用户添加挂件
		if(pendant != null && redisUtil.hget(RedisConstans.NEW_PENDANT + userId, pendant.getGiftId() + "") == null){
			redisUtil.hset(RedisConstans.NEW_PENDANT + userId, pendant.getGiftId() + "", pendant, RedisConstans.ONE_MONTH);
			NewPrizeVo finalPendant = pendant;
			executor.execute(()->{
				giftService.saveUserDress(ACTIVITY_ID, userId, finalPendant.getGiftId(), 1);
			});
		} else {
			pendant = null;
		}
		//批量插入卡牌记录
		activityCardService.saveBatch(recordList);
		//返回
		Map<String, Object> result = new HashMap<>();
		result.put("pendant", pendant);
		result.put("list", resultList);
		//计算翻牌总数
		redisUtil.incr(RedisConstans.NEW_CARD_NUM + userId, num, RedisConstans.ONE_MONTH);
		redisUtil.expire(RedisConstans.NEW_CARD_NUM + userId, RedisConstans.ONE_MONTH);
		//保存记录到redis
		for(Map.Entry<String, NewLotteryVo> entry : redisRecord.entrySet()){
			redisUtil.hset(RedisConstans.NEW_LOTTERY_RECORD + userId, entry.getKey(), entry.getValue(), RedisConstans.ONE_MONTH);
		}
		//表示今天已经抽过奖
		Integer dayLottery = redisUtil.get(RedisConstans.NEW_IS_CARD + userId + "_" + LocalDate.now());
		if(dayLottery == null){
			Integer hasReceiveFlame = redisUtil.get(RedisConstans.NEW_IS_FLAME + LocalDate.now().toString() + ":" + userId);
			if(hasReceiveFlame != null){
				redisUtil.set(RedisConstans.NEW_IS_CARD + userId + "_" + LocalDate.now().toString(), 1, RedisConstans.ONE_MONTH);
			}
		}
		log.info("methodName:openCard,批量翻牌成功,result={}", JSON.toJSONString(result));
		return result;
	}



	@Override
	public List<NewPrizeVo> prizeList(NewYearDto newYearDto) {
		return EXCHANGE_PRIZE_LIST;
	}


	@Override
	@Transactional(rollbackFor = Exception.class)
	public NewPrizeVo exchangePrize(NewYearDto newYearDto) {
		//验参
		Integer giftId = newYearDto.getGiftId();
		Integer type = newYearDto.getType();
		String userId = newYearDto.getUserId();
		if(giftId == null){
			throw new ServiceException("礼物id不能为空");
		}
		if(type == null){
			throw new ServiceException("类型不能为空");
		}
		//是否在活动时间内
		if(LocalDate.now().isAfter(EXCHANGE_END_TIME)){
			throw new ServiceException("已过兑换时间");
		}
		//校验是否有这个奖品
		NewPrizeVo target = null;
		for (NewPrizeVo newPrizeVo : EXCHANGE_PRIZE_LIST) {
			if(newPrizeVo.getGiftId().equals(giftId) && newPrizeVo.getType().equals(type)){
				target = newPrizeVo;
				break;
			}
		}
		if(target ==null){
			throw new ServiceException("兑换的奖品非法！");
		}
		//校验灯笼数是否足够
		ActivityWallet activityWallet = getActivityWallet(userId);
		if (activityWallet == null || activityWallet.getAmount2() < target.getLamp()) {
			throw new ServiceException("灯笼数不足");
		}
		int count = activityWalletMapper.reduceAmount2(activityWallet.getId(), target.getLamp());
		if(count < 1){
			throw new ServiceException("兑换失败，请稍候重试");
		}
		log.warn("methodName:exchangePrize,兑换奖品成功,userId={}, giftId={},name={},needLamp={},兑换前钱包={}", userId,target.getGiftId(),target.getName(),target.getLamp(),JSON.toJSONString(activityWallet));
		//保存物品
		giftService.savePrize(ACTIVITY_ID, 	userId, giftId, 2,1);
		//返回
		NewPrizeVo result = new NewPrizeVo();
		result.setGiftId(giftId).setName(target.getName()).setIcon(target.getIcon());
		return result;
	}


	@Override
	public Map<String, Object> balance(String userId) {
		Map<String,Object> map = new HashMap<>();
		//查询钱包钻石数
		Integer diamond = getDiamondsAmount(userId);
		map.put("diamond", diamond);
		map.put("flame", 0);
		map.put("lamp", 0);
		//查询火苗数 和 火苗数
		LambdaQueryWrapper<ActivityWallet> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(ActivityWallet::getActivityId, ACTIVITY_ID).eq(ActivityWallet::getUserId, userId);
		ActivityWallet activityWallet = activityWalletMapper.selectOne(wrapper);
		if(activityWallet == null){
			return map;
		}
		map.put("flame",activityWallet.getAmount1());
		map.put("lamp",activityWallet.getAmount2());
		//返回
		return map;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void exchangeFlame(NewYearDto newYearDto) {
		//是否在活动时间内
		if(!DateUtil.isBetweenTime(TIME_MAP.get("startTime"), TIME_MAP.get("endTime"))){
			throw new ServiceException("不在活动时间内");
		}
		Integer flame = newYearDto.getFlame();
		String userId = newYearDto.getUserId();
		if(flame == null){
			throw new ServiceException("兑换火苗数不能为空");
		}
		if(flame <= 0){
			throw new ServiceException("兑换火苗数必须大于0");
		}
		UserWallet wallet = userWalletMapper.selectByUserId(userId);

		if (wallet == null) {
			throw new ServiceException("钱包数据不存在");
		}
		//检查钻石是否足够兑换火苗
		if(flame > wallet.getDiamondsAmount() / 10){
			throw new ServiceException("钻石数不足");
		}
		ActivityWallet flameInfo = getActivityWallet(userId);
		//当前剩余火苗数
		Integer surplusFlame = flameInfo == null ? 0 : flameInfo.getAmount1();
		//扣除钻石数
		Integer needDiamond = flame * 10;
		//扣减钱包钻石数
		int row = userWalletMapper.reduceDiamondsAmount(wallet.getId(), needDiamond);
		if(row < 1){
			throw new ServiceException("兑换小火苗失败，请稍候重试");
		}
		//增加火苗
		if(flameInfo == null){
			ActivityWallet activityWallet = new ActivityWallet();
			activityWallet.setActivityId(ACTIVITY_ID);
			activityWallet.setUserId(userId);
			activityWallet.setAmount1(flame);
			activityWalletMapper.insert(activityWallet);
		} else{
			activityWalletMapper.addAmount1(flameInfo.getId(), flame);
		}
		// 添加转账记录
		UserAccountBook book = new UserAccountBook();
		book.setCurrencyType(6);
		book.setOrderId(userId);
		book.setAccountTitle("兑换火苗");
		book.setPaymentAccount(userId);
		book.setPaymentAmount(needDiamond);
		book.setPaymentAccountTotal(wallet.getDiamondsAmount());
		book.setPaymentAccountBalance(wallet.getDiamondsAmount() - needDiamond);
		book.setReceivingAccount(userId);
		book.setReceivingAmount(flame);
		book.setReceivingAccountTotal(surplusFlame);
		book.setReceivingAccountBalance(surplusFlame + flame);
		book.setNote("元旦活动兑换");
		userAccountBookMapper.insert(book);
		log.warn("methodName:exchangeFlame,兑换火苗成功,userId={},兑换数={},兑换前钻石={},火苗={}，兑换后钻石={},火苗={}", userId, flame, wallet.getDiamondsAmount(), surplusFlame, wallet.getDiamondsAmount() - needDiamond, surplusFlame + flame);
	}

	@Override
	public void receiveFlame(String userId){
		//是否在活动时间内
		if(!DateUtil.isBetweenTime(TIME_MAP.get("startTime"), TIME_MAP.get("endTime"))){
			throw new ServiceException("不在活动时间内");
		}
		long incr = redisUtil.incr(RedisConstans.NEW_IS_FLAME + LocalDate.now().toString() + ":" + userId);
		if(incr > 1){
			throw new ServiceException("今日已领取过小火苗");
		}
		//领取火苗
		ActivityWallet record = getActivityWallet(userId);
		//增加火苗
		if(record == null){
			ActivityWallet activityWallet = new ActivityWallet();
			activityWallet.setActivityId(ACTIVITY_ID);
			activityWallet.setUserId(userId);
			activityWallet.setAmount1(10);
			activityWalletMapper.insert(activityWallet);
		} else{
			activityWalletMapper.addAmount1(record.getId(), 10);
		}
		log.warn("methodName:receiveFlame,领取火苗成功,userId={}",userId);
	}

	//判断用户是否有勋章
	private boolean checkMedal(String userId) {
		String key = RedisConstans.NEW_IS_MEDAL + userId;
		Boolean result = redisUtil.get(key);
		if(result != null && result){
			return result;
		}

		//查询充值总值
		QueryWrapper<OrderDay> wrapper = new QueryWrapper<>();
		wrapper.lambda().eq(OrderDay::getUserId, userId);
		wrapper.select("ifnull(sum(cli_price),0) as total ");
		List<Map<String, Object>> rechargeList = orderDayMapper.selectMaps(wrapper);
		Double value = Double.valueOf(String.valueOf(rechargeList.get(0).get("total")));
		log.warn("methodName:checkMedal,查询充值总值，userId={},金额={}", userId,value);
		if(value >= 10){
			redisUtil.set(RedisConstans.NEW_IS_MEDAL + userId, true, RedisConstans.ONE_MONTH);
			return true;
		}

		//查收礼总值
		QueryWrapper<UserGift> wrapper2 = new QueryWrapper<>();
		wrapper2.lambda().eq(UserGift::getTargetId, userId);
		wrapper2.select("ifnull(sum(total_gift_value),0) as total ");
		List<Map<String, Object>> list2 = userGiftMapper.selectMaps(wrapper2);
		Long value2 = Long.valueOf(String.valueOf(list2.get(0).get("total")));
		log.warn("methodName:checkMedal,查收礼总值，userId={},礼物值={}", userId,value2);
		if(value2 >= 100){
			redisUtil.set(RedisConstans.NEW_IS_MEDAL + userId, true, RedisConstans.ONE_MONTH);
			return true;
		}

		//查送礼总值
		QueryWrapper<UserGift> wrapper1 = new QueryWrapper<>();
		wrapper1.lambda().eq(UserGift::getUserId, userId);
		wrapper1.select("ifnull(sum(total_gift_value),0) as total ");
		List<Map<String, Object>> list1 = userGiftMapper.selectMaps(wrapper1);
		Long value1 = Long.valueOf(String.valueOf(list1.get(0).get("total")));
		log.warn("methodName:checkMedal,查送礼总值，userId={},礼物值={}", userId,value1);
		if(value1 >= 100){
			redisUtil.set(RedisConstans.NEW_IS_MEDAL + userId, true, RedisConstans.ONE_MONTH);
			return true;
		}
		return false;
	}




	//查询钱包钻石余额
	private Integer getDiamondsAmount(String userId){
		QueryWrapper<UserWallet> wrapper = new QueryWrapper<>();
		wrapper.lambda().eq(UserWallet::getUserId, userId).last("limit 1");
		UserWallet userWallet = userWalletMapper.selectOne(wrapper);
		if (userWallet != null) {
			return userWallet.getDiamondsAmount();
		}
		return 0;
	}

	//查询火苗
	private ActivityWallet getActivityWallet(String userId){
		LambdaQueryWrapper<ActivityWallet> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(ActivityWallet::getActivityId, ACTIVITY_ID).eq(ActivityWallet::getUserId, userId);
		return activityWalletMapper.selectOne(wrapper);
	}

	public NewLotteryVo lottery(String userId, Integer small) {
		//Long roundId = IdSnowflake.getInstance().nextId();
		//是否有翻到气泡框
		Integer cache = redisUtil.get(RedisConstans.NEW_BUBBLE + userId);
		//查翻牌所有奖品
		List<NewLotteryVo> prizeList = sysDictMapper.selectPrizeList(PRIZE_CODE, cache, small);
		// 用户抽奖次数
		Integer roundCount = (Integer) redisUtil.hget(RedisConstans.ACTIVITY_NEW_LOTTERY_COUNT, userId);
		// 用户已抽奖的奖品总值
		Integer giftValue = (Integer) redisUtil.hget(RedisConstans.ACTIVITY_NEW_LOTTERY_PRIZE_VALUE, userId);
		// 我的中奖列表
		List<NewLotteryVo> myPrizeList = new ArrayList<>();
		if(giftValue == null || (roundCount != null && roundCount > USER_TOTAL_ROUND)){
			giftValue = 0;
		}
		//增加抽奖次数
		if (roundCount == null || roundCount > USER_TOTAL_ROUND) {
			roundCount = 0;
		}
		roundCount++;
		//必出奖品是否为空
		NewLotteryVo newLotteryVo = (NewLotteryVo) redisUtil.hget(RedisConstans.ACTIVITY_NEW_LOTTERY_MUST_PRIZE, userId);
		if (newLotteryVo != null) {// 走[指定概率]获取
			myPrizeList.add(newLotteryVo);
			redisUtil.hdel(RedisConstans.ACTIVITY_NEW_LOTTERY_MUST_PRIZE, userId);
			log.error("用户Id:{},当前缓存中抽奖次数为:{},【指定概率】大奖结果为:{},价值={},中奖概率:100%", userId,  roundCount, newLotteryVo.getName(), newLotteryVo.getValue());
		} else {
			newLotteryVo = randomPrize(prizeList);
			log.warn("用户Id:{},,当前抽奖次数:{},中奖结果为:{},价值={},中奖概率:{}", userId,  roundCount, newLotteryVo.getName(), newLotteryVo.getValue() ,newLotteryVo.getProbability());
			myPrizeList.add(newLotteryVo);
			// 叠加当前用户抽奖奖品价值
			giftValue += newLotteryVo.getValue();
			if (roundCount.equals(USER_TOTAL_ROUND) && giftValue != 0) {
				// 检查当前回合为最大回合时，生成对应补偿礼物
				NewLotteryVo mustGift = checkPriceSpreadAndGet(prizeList, giftValue);
				redisUtil.hset(RedisConstans.ACTIVITY_NEW_LOTTERY_MUST_PRIZE, userId, mustGift,RedisConstans.ONE_MONTH);
				log.warn("====个人抽奖回合结束,100抽奖品价值:{}====", giftValue);
			}
			redisUtil.hset(RedisConstans.ACTIVITY_NEW_LOTTERY_PRIZE_VALUE, userId, giftValue, RedisConstans.ONE_MONTH);
		}
		// 将当前查询数据保存到redis
		redisUtil.hset(RedisConstans.ACTIVITY_NEW_LOTTERY_COUNT, userId, roundCount, RedisConstans.ONE_MONTH);
		//返回结果
		return newLotteryVo;
	}

	public NewLotteryVo lotteryBatch(String userId, List<NewLotteryVo> prizeList) {
		// 用户抽奖次数
		Integer roundCount = (Integer) redisUtil.hget(RedisConstans.ACTIVITY_NEW_LOTTERY_COUNT, userId);
		// 用户已抽奖的奖品总值
		Integer giftValue = (Integer) redisUtil.hget(RedisConstans.ACTIVITY_NEW_LOTTERY_PRIZE_VALUE, userId);
		// 我的中奖列表
		List<NewLotteryVo> myPrizeList = new ArrayList<>();
		if(giftValue == null || (roundCount != null && roundCount > USER_TOTAL_ROUND)){
			giftValue = 0;
		}
		//增加抽奖次数
		if (roundCount == null || roundCount > USER_TOTAL_ROUND) {
			roundCount = 0;
		}
		roundCount++;
		//必出奖品是否为空
		NewLotteryVo newLotteryVo = (NewLotteryVo) redisUtil.hget(RedisConstans.ACTIVITY_NEW_LOTTERY_MUST_PRIZE, userId);
		if (newLotteryVo != null) {// 走[指定概率]获取
			myPrizeList.add(newLotteryVo);
			redisUtil.hdel(RedisConstans.ACTIVITY_NEW_LOTTERY_MUST_PRIZE, userId);
			log.error("用户Id:{},当前缓存中抽奖次数为:{},【指定概率】大奖结果为:{},价值={},中奖概率:100%", userId,  roundCount, newLotteryVo.getName(), newLotteryVo.getValue());
		} else {
			newLotteryVo = randomPrize(prizeList);
			log.warn("用户Id:{},,当前抽奖次数:{},中奖结果为:{},价值={},中奖概率:{}", userId,  roundCount, newLotteryVo.getName(), newLotteryVo.getValue() ,newLotteryVo.getProbability());
			myPrizeList.add(newLotteryVo);
			// 叠加当前用户抽奖奖品价值
			giftValue += newLotteryVo.getValue();
			if (roundCount.equals(USER_TOTAL_ROUND) && giftValue != 0) {
				// 检查当前回合为最大回合时，生成对应补偿礼物
				NewLotteryVo mustGift = checkPriceSpreadAndGet(prizeList, giftValue);
				redisUtil.hset(RedisConstans.ACTIVITY_NEW_LOTTERY_MUST_PRIZE, userId, mustGift,RedisConstans.ONE_MONTH);
				log.warn("====个人抽奖回合结束,100抽奖品价值:{}====", giftValue);
			}
			redisUtil.hset(RedisConstans.ACTIVITY_NEW_LOTTERY_PRIZE_VALUE, userId, giftValue, RedisConstans.ONE_MONTH);
		}
		// 将当前查询数据保存到redis
		redisUtil.hset(RedisConstans.ACTIVITY_NEW_LOTTERY_COUNT, userId, roundCount, RedisConstans.ONE_MONTH);
		//返回结果
		return newLotteryVo;
	}


	/**
	 * 判断获得礼物价值和总礼物价值差生成来相应个人的奖池数据，并返回个人奖池的抽奖奖品概率列表
	 */
	private NewLotteryVo checkPriceSpreadAndGet(List<NewLotteryVo> giftConfigList, Integer giftValue) {
		NewLotteryVo result = null;
		for (NewLotteryVo newLotteryVo : giftConfigList) {
			if (giftValue < 5000) {// 出5千钻礼物
				if (newLotteryVo.getValue().equals(50000)) {
					result = newLotteryVo;
					break;
				}
			} else if (giftValue >= 5000 && giftValue < 7000) {// 出2千钻礼物
				if (newLotteryVo.getValue().equals(2000)) {
					result = newLotteryVo;
					break;
				}
			} else if (giftValue >= 1000 && giftValue < 2000) {// 出660礼物
				if (newLotteryVo.getValue().equals(6600)) {
					result = newLotteryVo;
					break;
				}
			}
		}
		if(result != null){
			result.setName(CARD_PRIZE_MAP.get(result.getGiftId()).getName()).setIcon(CARD_PRIZE_MAP.get(result.getGiftId()).getIcon());
		}
		return result;
	}

	/**
	 * 抽奖概率，概率不带小数点
	 * @return
	 */
	public static NewLotteryVo randomPrize(List<NewLotteryVo> prizes) {
		Integer sum = prizes.stream().mapToInt(t -> t.getProbability()).sum();
		NewLotteryVo prize = null;
		int rate = 0;
		int random = RandomUtil.randomInt(0, sum);
		for (NewLotteryVo item : prizes) {
			// 中奖概率
			rate += item.getProbability();
			if (random < rate) {
				prize = item;
				break;
			}
		}
		prize.setName(CARD_PRIZE_MAP.get(prize.getGiftId()).getName()).setIcon(CARD_PRIZE_MAP.get(prize.getGiftId()).getIcon());
		return prize;
	}

	//插入领取记录表
	private void insertRecord(String userId, Integer giftId, String name, Integer value){
		ActivityRecord record = new ActivityRecord();
		record.setActivityId(ACTIVITY_ID);
		record.setUserId(userId);
		record.setGiftId(giftId);
		record.setContent(name);
		record.setValue(value);
		record.setType(0);
		activityRecordMapper.insert(record);
	}

	//获取礼物信息
	private Map<String, String> getGiftInfo(Integer giftId){
		Map<String, String> map = new HashMap<>();
		GiftConfig giftConfig = giftConfigMapper.selectById(giftId);
		map.put("name", giftConfig.getName());
		map.put("icon", StringUtils.isBlank(giftConfig.getIconUrl()) ? "" : giftConfig.getIconUrl());
		if(giftConfig.getGiftType() == 1){
			//装扮物品,名称包含天数
			LambdaQueryWrapper<SysDict> wrapper = new LambdaQueryWrapper<>();
			wrapper.eq(SysDict::getCode,"DRESS_UP").eq(SysDict::getId, giftConfig.getDressId());
			SysDict sysDict = sysDictMapper.selectOne(wrapper);
			if(sysDict != null && StringUtils.isNotBlank(sysDict.getProperty4())){
				map.put("name", giftConfig.getName() + "（"+ sysDict.getProperty4() +"天）");

			}
		}
		return map;
	}

	//获取新装扮信息
	private Map<String, String> getDressUpInfo(Integer giftId){
		Map<String, String> map = new HashMap<>();
		DressUpConfig dressUpConfig = dressUpConfigMapper.selectById(giftId);
		map.put("name", dressUpConfig.getName());
		map.put("icon", dressUpConfig.getImgUrl());
		if(dressUpConfig.getDuration() != null && dressUpConfig.getDuration() != 0){
			map.put("name", dressUpConfig.getName() + "(" + dressUpConfig.getDuration() + "天)");
		}
		return map;
	}

}
